﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AvalonDock;
using System.Windows.Forms.Integration;
using System.Diagnostics;
using System.ComponentModel;
using System.Reflection;
using System.IO;

namespace FRCDock
{
    /// <summary>
    /// Interaction logic for MainWnd.xaml
    /// </summary>
    public partial class MainWnd : Microsoft.Windows.Controls.Ribbon.RibbonWindow
    {
        WindowsFormsHost _PropGridHost = new WindowsFormsHost();

        private event RoutedEventHandler _restorEvent;

        public MainWnd()
        {
            //this.Resources.MergedDictionaries
            //    .Add(Microsoft.Windows.Controls.Ribbon.PopularApplicationSkins.Office2007Black);
            this.Resources.MergedDictionaries
                .Add(Microsoft.Windows.Controls.Ribbon.PopularApplicationSkins.Office2007Silver);


            InitializeComponent();
            InitObjectExplorer();
        }


        void InitObjectExplorer()
        {
            DependencyPropertyDescriptor prop =
                DependencyPropertyDescriptor.FromProperty(DockableContent.StatePropertyKey.DependencyProperty, typeof(DockableContent));
            prop.AddValueChanged(_solutionExplorer, this.OnLogEventStateChanged);
            prop.AddValueChanged(_objectExplorerHost, this.OnLogEventStateChanged);
            prop.AddValueChanged(_eventsLogWindow, this.OnLogEventStateChanged);
            _dockingManager.PropertyChanged += new PropertyChangedEventHandler(_dockingManager_PropertyChanged);

            System.Windows.Forms.PropertyGrid _PropGrid = new System.Windows.Forms.PropertyGrid();
            _PropGrid.SelectedObject = _dockingManager;
            _PropGrid.Name = "_PropertyGrid";
            _PropGridHost.Child = _PropGrid;
            this._objectExplorerHost.Content = _PropGridHost;

            //_PropGridHost.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(_PropGridHost_GotKeyboardFocus);
            ////((IKeyboardInputSink)_PropGridHost)
            //DockableContent cnt = new DockableContent();
            //cnt.Title = "Test";
            //cnt.Name = "test";
            //WindowsFormsHost tempHost = new WindowsFormsHost();
            //tempHost.Child = new System.Windows.Forms.TextBox();
            //cnt.Content = tempHost;
            //_dockingManager.Show(cnt, DockableContentState.Docked, AnchorStyle.Left);
            //CommandManager.AddPreviewCanExecuteHandler(_dockingManager, new CanExecuteRoutedEventHandler(OnCanExecuteCommand));
            CommandManager.AddPreviewExecutedHandler(_dockingManager, new ExecutedRoutedEventHandler(ExecuteCommand));
        }

        void ExecuteCommand(object sender, ExecutedRoutedEventArgs e)
        {
            if (e.Command == ApplicationCommands.Close &&
                e.Source is DocumentPane)
            {
                //e.Handled = true;
            }
        }

        void OnCanExecuteCommand(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Command == ApplicationCommands.Close)
            {
                if (sender == _dockingManager)
                {

                }
            }
        }

        void _PropGridHost_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {

        }

        private void NewDocuments_Click(object sender, RoutedEventArgs e)
        {
            int i = 1;

            IEnumerable<FRCDocument> docs = _dockingManager.Documents.Cast<FRCDocument>().Where<FRCDocument>(d => d.IsChanged);


            int baseCount = _dockingManager.Documents.Length;
            while (i <= 4)
            {
                FRCDocument doc = new FRCDocument();
                doc.Title = "Document " + (i + baseCount);
                doc.InfoTip = "Info tipo for " + doc.Title;
                doc.ContentTypeDescription = "Sample document";
                doc.Closing += new EventHandler<CancelEventArgs>(doc_Closing);
                doc.Closed += new EventHandler(doc_Closed);
                _documentsHost.Items.Add(doc);

                i++;
            }
        }

        /// <summary>
        /// When document is closed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void doc_Closed(object sender, EventArgs e)
        {
            Debug.WriteLine(((DocumentContent)sender).Title + " closed");
        }

        /// <summary>
        /// When document is closing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void doc_Closing(object sender, CancelEventArgs e)
        {
            Debug.WriteLine(((DocumentContent)sender).Title + " closing");
        }


        private void ShowProperties_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink link = sender as Hyperlink;
            if (link.Name == "ShowProperties_AutoHide")
                ShowWindow(_solutionExplorer, DockableContentState.AutoHide);
            else if (link.Name == "ShowProperties_FloatingWindow")
                ShowWindow(_solutionExplorer, DockableContentState.FloatingWindow);
            else
                ShowWindow(_solutionExplorer, DockableContentState.Docked);
        }

        private void ShowExplorer_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink link = sender as Hyperlink;
            if (link.Name == "ShowExplorer_AutoHide")
                ShowWindow(_outputWindow, DockableContentState.AutoHide);
            else if (link.Name == "ShowExplorer_FloatingWindow")
                ShowWindow(_outputWindow, DockableContentState.FloatingWindow);
            else
                ShowWindow(_outputWindow, DockableContentState.Docked);
        }

        private void ShowEventsLog_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink link = sender as Hyperlink;
            if (link.Name == "ShowEventsLog_AutoHide")
                ShowWindow(_eventsLogWindow, DockableContentState.AutoHide);
            else if (link.Name == "ShowEventsLog_FloatingWindow")
                ShowWindow(_eventsLogWindow, DockableContentState.FloatingWindow);
            else
                _dockingManager.Show(_eventsLogWindow, DockableContentState.Docked, AnchorStyle.Right);
        }

        private void ShowProperty_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink link = sender as Hyperlink;
            if (link.Name == "ShowProperty_AutoHide")
                ShowWindow(_objectExplorerHost, DockableContentState.AutoHide);
            else if (link.Name == "ShowProperty_FloatingWindow")
                ShowWindow(_objectExplorerHost, DockableContentState.FloatingWindow);
            else
                _dockingManager.Show(_objectExplorerHost, DockableContentState.Docked, AnchorStyle.Right);
        }

        void ShowWindow(DockableContent contentToShow, DockableContentState desideredState)
        {
            if (desideredState == DockableContentState.AutoHide ||
                desideredState == DockableContentState.FloatingWindow)
            {
                _dockingManager.Show(contentToShow, desideredState);
            }
            else
                _dockingManager.Show(contentToShow, DockableContentState.Docked);
        }


        void OnLogEventStateChanged(object sender, EventArgs e)
        {
            DockableContent content = sender as DockableContent;

            if (content.ContainerPane is DockablePane)
            {
                _txtLog.AppendText(
                    string.Format("[{0}] '{1}' changed state to '{2}' (Anchor={3})", DateTime.Now.ToLongTimeString(), content.Title, content.State, ((DockablePane)content.ContainerPane).Anchor));
            }
            else
            {
                _txtLog.AppendText(
                    string.Format("[{0}] '{1}' changed state to '{2}'", DateTime.Now.ToLongTimeString(), content.Title, content.State));
            }
            _txtLog.AppendText(Environment.NewLine);
            _txtLog.ScrollToEnd();
        }

        /// <summary>
        /// Append the change of the layout to the Log panel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _dockingManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ActiveContent" && _dockingManager.ActiveContent != null)
            {
                if (_dockingManager.ActiveContent != null)
                {

                    DockablePane containerPane = _dockingManager.ActiveContent.ContainerPane as DockablePane;
                    _txtLog.AppendText(
                        string.Format("[{0}] '{1}' is the active content (Anchor = {2})", DateTime.Now.ToLongTimeString(), _dockingManager.ActiveContent.Title, containerPane != null ? containerPane.Anchor.ToString() : "Document!"));
                    _txtLog.AppendText(Environment.NewLine);
                    _txtLog.ScrollToEnd();
                }
            }
            else if (e.PropertyName == "ActiveDocument" && _dockingManager.ActiveDocument != null)
            {
                if (_dockingManager.ActiveDocument != null)
                {
                    _txtLog.AppendText(
                        string.Format("[{0}] '{1}' is the active document", DateTime.Now.ToLongTimeString(), _dockingManager.ActiveDocument.Title));

                    _txtLog.AppendText(Environment.NewLine);
                    _txtLog.ScrollToEnd();
                }
            }
        }

        /// <summary>
        /// When window is closing, save the layout file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            if (_dockingManager != null)
                _dockingManager.PropertyChanged -= new PropertyChangedEventHandler(_dockingManager_PropertyChanged);

            DependencyPropertyDescriptor prop =
                DependencyPropertyDescriptor.FromProperty(DockableContent.StatePropertyKey.DependencyProperty, typeof(DockableContent));
            prop.RemoveValueChanged(_solutionExplorer, this.OnLogEventStateChanged);
            prop.RemoveValueChanged(_outputWindow, this.OnLogEventStateChanged);
            prop.RemoveValueChanged(_eventsLogWindow, this.OnLogEventStateChanged);

            string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
                + @"\FRCDock.Layout.xml";

            _dockingManager.SaveLayout(path);
        }

        /// <summary>
        /// The API to save the layout
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveLayout_Click(object sender, RoutedEventArgs e)
        {
            string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
                + @"\FRCDock.Layout.xml";

            _dockingManager.SaveLayout(path);
        }

        /// <summary>
        /// The API to restore the layout
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RestoreLayout_Click(object sender, RoutedEventArgs e)
        {
            string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
                + @"\FRCDock.Layout.xml";
            if (!File.Exists(path))
                return;

            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            _dockingManager.RestoreLayout(fs);

            fs.Close();
        }

        /// <summary>
        /// The API to load/unload 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowDockingManager_Checked(object sender, RoutedEventArgs e)
        {
            //test the load/unload event putting docking manager out of the logical/visual tree
            // FRCContainer.Content = ShowDockingManager.IsChecked ? null : _dockingManager;
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.Handled = true;
            e.CanExecute = false;
        }

        /// <summary>
        /// When the window is loaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // When the window is loaded, it should restore the original values
            // With this in place, we can ship the layout file with the default installation.  
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button Clicked");
        }

        /// <summary>
        /// This API is critical, once DockingManager is loaded, then it is time to restore
        /// the layout
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _dockingManager_Loaded(object sender, RoutedEventArgs e)
        {
            RestoreLayout_Click(sender, e);
        }

        private void _documentsHost_GotMouseCapture(object sender, MouseEventArgs e)
        {
            System.Windows.Forms.PropertyGrid _PropGrid = new System.Windows.Forms.PropertyGrid();
            _PropGrid.SelectedObject = _documentsHost;
            _PropGrid.Name = "_PropertyGrid";
            _PropGridHost.Child = _PropGrid;
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
        }

        private void OnCloseApplication(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }
    }
}
